package nbcp

import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.beans.factory.annotation.Qualifier
import org.springframework.boot.SpringApplication
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.web.reactive.context.ReactiveWebServerApplicationContext
import org.springframework.cloud.client.discovery.EnableDiscoveryClient
import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver
import org.springframework.cloud.gateway.filter.ratelimit.RedisRateLimiter
import org.springframework.cloud.gateway.route.RouteLocator
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder
import org.springframework.context.ApplicationContext
import org.springframework.context.annotation.Bean
import org.springframework.web.server.ServerWebExchange
import reactor.core.publisher.Mono
import java.net.URI

@SpringBootApplication
@EnableDiscoveryClient
class MainApplication {
    companion object {
        val logger = LoggerFactory.getLogger(this::class.java.declaringClass)
    }

    class RemoteAddrKeyResolver : KeyResolver {
        override fun resolve(exchange: ServerWebExchange): Mono<String> {
            var path = exchange.getRequest().getPath().value();   //用户访问的接口地址
            return Mono.just(path);
        }
    }

    @Bean(name = ["remoteAddrKeyResolver"])
    fun remoteAddrKeyResolver(): RemoteAddrKeyResolver {
        return RemoteAddrKeyResolver()
    }

    @Bean(name = ["redisRateLimiter"])
    public fun customRedisRateLimiter(): RedisRateLimiter {
        var customRedisRateLimiter = RedisRateLimiter(100, 100);
        customRedisRateLimiter.setApplicationContext(applicationContext);
        return customRedisRateLimiter;
    }

    @Bean
    fun authorizationFilter( ): AuthorizationFilter {
        return AuthorizationFilter()
    }


    @Autowired
    lateinit var applicationContext: ApplicationContext;

    @Autowired
    lateinit var redisRateLimiter: RedisRateLimiter

//    @Bean
//    fun myRoutes(builder: RouteLocatorBuilder,
//                 @Qualifier("remoteAddrKeyResolver") remoteAddrKeyResolver: RemoteAddrKeyResolver,
//                 @Qualifier("redisRateLimiter") redisRateLimiter: RedisRateLimiter
//    ): RouteLocator {
//        return builder.routes()
//                .route { p ->
//                    p
//                            .predicate {
//                                it.addUrlTransformer { "/corp/**" }
//                                true
//                            }
//                            .filters { f ->
//                                f.stripPrefix(1)
//
//                                f.requestRateLimiter { config ->
//                                    //                                    var d = RedisRateLimiter(100, 30);
////                                    it.rateLimiter = d;
//                                    config.rateLimiter = redisRateLimiter
//                                    config.keyResolver = remoteAddrKeyResolver
//                                }
//                                f.hystrix {
//                                    it.fallbackUri = URI("forward:fallback")
//                                }
//                            }
//
//                            .uri("lb://corp-api/**")
//                }
//                .route { p ->
//                    p
//                            .predicate {
//                                it.addUrlTransformer { "/corp-api/**" }
//                                true
//                            }
//                            .filters { f ->
//                                f.stripPrefix(1)
//                            }
//                            .uri("lb://corp-api/**")
//                }
//                .build()
//    }

}


fun main(args: Array<String>) {
    var context = SpringApplication.run(MainApplication::class.java, *args) as ReactiveWebServerApplicationContext

    MainApplication.logger.trace("""
        ================================================
             ${context.debugServerInfo}
        ================================================
""")
}


val ReactiveWebServerApplicationContext.debugServerInfo: String
    get() {
        var serverName = this.webServer::class.java.simpleName
        var applicationName = this.environment.getProperty("spring.application.name")
        var version = this.environment.activeProfiles.joinToString(",")
        var cloudVersion = this.environment.getProperty("spring.cloud.config.profile") ?: ""
        var port = this.environment.getProperty("server.port")

        if (cloudVersion.isNotEmpty()) {
            version += "-cloud-" + cloudVersion
        }

        return "${serverName}:${port} -- ${applicationName}:${version}"
    }